﻿using System;
using System.ComponentModel.Composition;
using System.Linq;
using Security.Domain;
using Security.Events.Commands;
using Security.Helpers;
using Security.Specs.Common;
using Security.Specs.DataLayer;
using Security.Specs.Services;
using Security.Specs.Implementation.Common;

namespace Security.Specs.Implementation.Services
{
    [Export(typeof(IServerLoginService))]
    internal class ServerLoginService : IServerLoginService
    {
        private readonly ISecurityDataModel model;
        private ValidationService<ServerLogin> validationServiceForNewLogin;

        [ImportingConstructor]
        public ServerLoginService(ISecurityDataModel model)
        {
            this.model = model;
            InitializeValidationService();
        }

        public ServerLogin New()
        {
            return new ServerLogin();
        }

        public ErrorCollection ValidateExistedLogin(ServerLogin serverLogin)
        {
            return ErrorCollection.Empty();
        }

        public ErrorCollection ValidateNewLogin(ServerLogin login)
        {
            return validationServiceForNewLogin.GetErrors(login);
        }

        private void InitializeValidationService()
        {
            validationServiceForNewLogin = new ValidationService<ServerLogin>();
            validationServiceForNewLogin.AddRule(l => string.IsNullOrWhiteSpace(l.Name), StandardErrorReports.NamePropertyNotSet);
            validationServiceForNewLogin.AddRule(l => string.IsNullOrWhiteSpace(l.Password), PasswordNotSet);
            validationServiceForNewLogin.AddRule(l => l.Password.Length < 6, NotValidWindowsPassword);
            validationServiceForNewLogin.AddRule(l => model.ServerLogins.Any(sl => sl.Name == l.Name), DuplicateLogin);
        }

        private ErrorReport DuplicateLogin(ServerLogin login)
        {
            return ErrorReport.Create().
                            InObject(login).
                            WithMessage(Strings.DuplicateLogin()).
                            InvalidPropertyName(Property.Name<ServerLogin>(l => l.Name)).
                            Severity(ErrorSeverity.Error);
        }

        private ErrorReport NotValidWindowsPassword(ServerLogin login)
        {
            return ErrorReport.Create().
                            InObject(login).
                            WithMessage(Strings.NotValidWindowsPassword()).
                            InvalidPropertyName(Property.Name<ServerLogin>(l => l.Password)).
                            Severity(ErrorSeverity.Error);
        }

        private ErrorReport PasswordNotSet(ServerLogin login)
        {
            return ErrorReport.Create().
                            InObject(login).
                            WithMessage(Strings.NotValidWindowsPassword()).
                            InvalidPropertyName(Property.Name<ServerLogin>(l => l.Password)).
                            Severity(ErrorSeverity.Error);
        }
    }
}